package com.youcheng.configcenter.provider;

import com.youcheng.configcenter.dao.ApplicationConfigDao;
import com.youcheng.configcenter.dao.ApplicationConfigDaoImpl;
import com.youcheng.configcenter.dao.DataAccessBase;
import com.youcheng.configcenter.exception.ConfigCenterServiceException;
import com.youcheng.configcenter.factory.ResourceConvertorFactory;
import com.youcheng.configcenter.model.ConfigFileDO;
import com.youcheng.configcenter.model.ConfigFileStoreEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;

/**
 * @author sunhongmin
 * @date 2022/10/21 16:22
 * @description
 */
@Slf4j
public class DataBaseConfigProvider implements RemoteConfigProvider {

    private final ConfigurableEnvironmentDecorator.DataBaseConfigBean dataBaseConfigBean;
    private final ConfigurableEnvironmentDecorator.ConfigFileConfigBean configFileConfigBean;

    public DataBaseConfigProvider(ConfigurableEnvironmentDecorator.DataBaseConfigBean dataBaseConfigBean, ConfigurableEnvironmentDecorator.ConfigFileConfigBean configFileConfigBean) {
        this.dataBaseConfigBean = dataBaseConfigBean;
        this.configFileConfigBean = configFileConfigBean;
    }

    @Override
    public Properties load() {
        DataAccessBase dataAccessBase = new DataAccessBase(dataBaseConfigBean.getDriverClassName(), dataBaseConfigBean.getUrl(), dataBaseConfigBean.getUserName(), dataBaseConfigBean.getPassword());
        ApplicationConfigDao applicationConfigDao = new ApplicationConfigDaoImpl(dataAccessBase);
        try {
            ConfigFileDO configFileLast = applicationConfigDao.findConfigFileLast(configFileConfigBean.getFileId(), configFileConfigBean.getProfile());
            if (Objects.isNull(configFileLast)) {
                log.error("load config file from db error , configFileConfigBean:{}", configFileConfigBean);
                return null;
            }
            configFileLast = this.checkAndGetIncrementConfig(configFileLast);
            if(Objects.isNull(configFileLast)){
                log.warn("config is not changed, method return ...");
                return null;
            }
            String content = configFileLast.getContent();
            if (!StringUtils.hasLength(content)) {
                log.warn("load config file from db error, contenr is empty, content:{}", content);
                return null;
            }

            String fileName = String.format("%s.%s", configFileLast.getName(), configFileLast.getExtension());
            return ResourceConvertorFactory.getResourceConvertorInstance(fileName).convertToProperties(content);

        } catch (ConfigCenterServiceException e) {
            log.error("load config file from db error", e);
            throw new RuntimeException(e);
        }
    }

    /**
     * 基于版本以及最后更新时间比对，检查配置是否有变更
     * @param currentConfigFile 当前获取的最新配置值
     * @return 增量配置文件或者null
     */
    private ConfigFileDO checkAndGetIncrementConfig(ConfigFileDO currentConfigFile) {
        Map<String, List<ConfigFileDO>> localConfigStoreGroupMap = ConfigFileStoreEnum.LOCAL_CONFIG_FILE_STORE.getConfigGroupMap();
        List<ConfigFileDO> storeConfigFileList = localConfigStoreGroupMap.get(ConfigFileStoreEnum.DEFAULT_GROUP_NAME);
        if (CollectionUtils.isEmpty(storeConfigFileList)) {
            localConfigStoreGroupMap.put(ConfigFileStoreEnum.DEFAULT_GROUP_NAME, Collections.singletonList(currentConfigFile));
            return currentConfigFile;
        }

        ConfigFileDO storeConfigFile = storeConfigFileList.stream().findFirst().orElse(new ConfigFileDO());
        if (Objects.nonNull(storeConfigFile.getVersion()) && Objects.equals(storeConfigFile.getVersion(), currentConfigFile.getVersion())) {
            if (Objects.nonNull(storeConfigFile.getLastUpdatedTime()) && Objects.equals(storeConfigFile.getLastUpdatedTime().getTime(), currentConfigFile.getLastUpdatedTime().getTime())) {
                return null;
            }
        }

        localConfigStoreGroupMap.put(ConfigFileStoreEnum.DEFAULT_GROUP_NAME, Collections.singletonList(currentConfigFile));
        return currentConfigFile;

    }

}
